package threadDemo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//question1:A、B、C 三个线程，循环10次，打印出自己的名称，A一次，B三次，C五次，ABBBCCCCC，ABBBCCCCC
//condition + lock实现
public class ConditionPrintDemo {

    private int flag = 1; //作为abc的标识符   打印哪个
    private static Lock lock = new ReentrantLock();
    private static final Condition conditionA = lock.newCondition();
    private static final Condition conditionB = lock.newCondition();
    private static final Condition conditionC = lock.newCondition();
    private static final Condition[] conditions = {conditionA, conditionB, conditionC};

    //private static CountDownLatch countDownLatch = new CountDownLatch(10); //使用闭锁计数器
    //哪个线程等待与否的标记,flag的值：
    // 1 线程A打印，否则等待，同时将标记设置为2，唤醒线程B
    // 2 线程B打印，否则等待，同时将标记设置为3，唤醒线程C
    // 3 线程C打印，否则等待，同时将标记设置为1，唤醒线程A  外层一次循环结束。
    public void print(int loopNum, int flagNum, String str, Condition curConditon, Condition nextConditon){
        try {
            lock.lock();
            if (flag % 3 != flagNum) curConditon.await();
            for (int i = 0; i < loopNum; i++) {
                System.out.print(str);
            }
            flag +=1;
            nextConditon.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printA(int loopNum) {
        try {
            lock.lock();
            if (flag != 1) {
                conditionA.await();
            }
            for (int i = 0; i < loopNum; i++) {
                System.out.print("a");
            }
            flag = 2;
            conditionB.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB(int loopNum) {
        try {

            lock.lock();
            if (flag != 2) {
                conditionB.await();
            }
            for (int i = 0; i < loopNum; i++) {
                System.out.print("b");
            }
            flag = 3;
            conditionC.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC(int loopNum) {
        try {
            lock.lock();
            if (flag != 3) {
                conditionC.await();
            }
            for (int i = 0; i < loopNum; i++) {
                System.out.print("c");
            }
            System.out.print("\n");
            flag = 1;
            conditionA.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ConditionPrintDemo demo = new ConditionPrintDemo();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.print(1 , 1 , "a" , conditionA , conditionB);
            }
        }).start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.print(3 , 2 , "b" , conditionB , conditionC);
            }
        }).start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.print(5 , 0 , "c" , conditionC , conditionA);
            }
        }).start();
    }

}